<template>
  <Fragment>
    <!-- data 数据递归了需要元数据 -->
    <template v-for="item in data">
      <tr :key="item.id" class="progress_position mouse_hover">
        <!-- 按月份渲染渲染 -->
        <template v-if="active === sizeDict.MONTH" >
          <template v-for="item in dateList">
            <template v-for="item2 in item.children">
              <td v-if="item2.value" :key="onlyKey(item.value +'-' + item2.value)" :style="{minWidth: monthWidth + 'px'}" ></td>
            </template>
          </template>
        </template>
        <!-- 按日期份渲染渲染 -->
        <template v-if="active === sizeDict.DAY">
          <template v-for="item in dateList">
            <template v-for="item2 in item.children">
              <template v-for="item3 in item2.children">
                <td :key="onlyKey(item.value +'-' +item2.value +'-'+item3)" :style="{minWidth: width + 'px'}" ></td>
              </template>
            </template>
          </template>
        </template>
        <!-- 显示项目名 -->
        <div class="task_name" :style="{left: active === sizeDict.DAY ? (total_time(startTagTime, item.endTime)) * width + 20 +  'px' : (monthGrain(getFirstDate(startTagTime), item.endTime) - 1/30) * monthWidth + 20 + 'px'}">{{item.taskName}}</div>
        <!-- 按月份显示实际进度 -->
        <!-- startTagTime 本月的第一天开始算 -->
        <el-progress v-if="active === sizeDict.MONTH" :style="{
                  left: (monthGrain(getFirstDate(startTagTime), item.startTime) - 1/30) * monthWidth + 1 + 'px',
                  width: monthGrain(item.startTime, item.endTime) * monthWidth + 'px'
                }" class="progress_ing" :text-inside="true" :stroke-width="14" :percentage="item.actual_process * 100" :status="projectStatus(currentProcess(item.startTime, item.totalTime), item.actual_process)"></el-progress>
        <!-- 总进度 -->
        <el-progress :style="{
                  left: active === sizeDict.MONTH ? (monthGrain(getFirstDate(startTagTime), item.startTime) - 1/30) * monthWidth + 1 +  'px' :  (total_time(startTagTime, item.startTime) - 1) * (width + 1) + 'px',
                  width: active === sizeDict.MONTH ? monthGrain(item.startTime, item.endTime) * monthWidth + 'px' : total_time(item.startTime, item.endTime) * (width + 1) + 'px'
                }" class="progress_total" :text-inside="true" :stroke-width="14" :percentage="currentProcess(item.startTime, item.totalTime)  * 100"></el-progress>
        <!-- 按日期显示实际进度 -->
        <el-progress v-if="active === sizeDict.DAY" :style="{
                  left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) +  'px',
                  width: total_time(item.startTime, item.endTime) * (width + 1)  + 'px'
                }" class="progress_ing" :text-inside="true" :stroke-width="14" :percentage="item.actual_process * 100" :status="projectStatus(currentProcess(item.startTime, item.totalTime), item.actual_process)"></el-progress>
        <!-- 项目层级标记 -> 子节点区间 -->
        <!-- 日期开始 -->
        <template v-if="item.children.length && dataList.hideList[item.id] !== true && active === sizeDict.DAY">
          <div :class="(item.children.length && dataList.hideList[item.id] !== true) ? 'progress_start' : ''" :style="{
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) +  'px',
            height: childrenCount(item.children) * height  + 'px'
            }" />
          <!-- 结束 -->
          <div :class="(item.children.length && dataList.hideList[item.id] !== true) ? 'progress_start' : ''" :style="{
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) + total_time(item.startTime, item.endTime) * (width + 1) +  'px',
            height: childrenCount(item.children) * height + 'px'
            }" />
        </template>
        <template v-if="item.children.length && dataList.hideList[item.id] !== true && active === sizeDict.MONTH">
          <div :class="(item.children.length && dataList.hideList[item.id] !== true) ? 'progress_start' : ''" :style="{
            left: (monthGrain(getFirstDate(startTagTime), item.startTime) - 1/30) * monthWidth + 'px',
            height: childrenCount(item.children) * height  + 'px'
            }" />
        </template>
        <!-- 前置任务箭头指向 -->
        <template v-if="item.predecessors && active === sizeDict.DAY">
          <!-- 开始的横线
            wttaValue：如果 前辈项目的日期 小于 当前项目开始的日期
             > width:  就取 距离前辈的距离 否则 固定20
             > left：如果  就取-值 否则 取+
           -->
          <div :style="{
            width: (wttaValue(item) ? predecessorsHorizontalDistance(item) : 20) + 'px',
            height: '2px',
            top: -predecessorsVerticalDistance(item) + 'px',
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) - 10 + (wttaValue(item) ? -predecessorsHorizontalDistance(item) : predecessorsHorizontalDistance(item) - 20) +  'px'
            }" class="associate_line"></div>
          <!-- 绕开进度的竖线
            wttaValue：如果 前辈项目的日期 小于 当前项目开始的日期
             > left：如果  就取0 否则 取距离前辈的距离
           -->
          <div :style="{
            width: '2px',
            height: predecessorsVerticalDistance(item) + 'px',
            top: -predecessorsVerticalDistance(item) + 'px',
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) - 10 + (wttaValue(item) ? 0 : predecessorsHorizontalDistance(item)) +  'px'
            }" class="associate_line"></div>
          <!-- 绕开进度的横线
            wttaValue：如果 前辈项目的日期 小于 当前项目开始的日期
             > width:  就取 0 否则 距离前辈的距离
           -->
          <div :style="{
            width: wttaValue(item) ? 0 : predecessorsHorizontalDistance(item) + 'px',
            height: '2px',
            top: '-1px',
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) - 10  +  'px'
            }" class="associate_line"></div>
          <!-- 指向自己的竖线 -->
          <div :style="{
            width: '2px',
            height: '20px',
            top: '0px',
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) - 10 +  'px'
            }" class="associate_line"></div>
          <!-- 指向自己的横线 -->
          <div :style="{
            width: '10px',
            height: '2px',
            top: '18px',
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) - 10 +  'px'
            }" class="associate_line"></div>
          <!-- 指向自己的箭头 -->
          <span :style="{
            top: '15px',
            left: (total_time(startTagTime, item.startTime) - 1) * (width + 1) - 8 +  'px'
            }" class="associate_arrow" />
        </template>
      </tr>
      <template v-if="item.children.length && dataList.hideList[item.id] !== true">
        <GanttProcess :data="item.children" :active="active" :dateList="dateList" :key="'children' + item.id" :dataList="dataList" :startTagTime="startTagTime" />
      </template>
    </template>
  </Fragment>
</template>

<script>
import GanttProcess from '@/components/GanttProcess';
import { sizeDict, width, onlyKey, monthWidth, height, oneDay } from '@/utils/GanttDicts'
import { total_time, currentProcess, projectStatus, monthGrain, getFirstDate } from '@/utils/GanttUtil'

export default {
  name: 'GanttProcess',
  data() {
    return {
      sizeDict,
      width: width + 1,
      offset: 500,
      total_time,
      currentProcess,
      onlyKey,
      monthWidth,
      projectStatus,
      monthGrain,
      getFirstDate,
      height
    }
  },
  props: {
    data: {
      type: Array,
      default: () => []
    },
    dateList: {
      type: Object,
      default: () => { }
    },
    active: {
      type: String,
      default: 'active'
    },
    dataList: {
      type: Object,
      default: () => { }
    },
    startTagTime: {
      type: String,
      default: ''
    },
  },
  components: {
    GanttProcess,
  },
  methods: {
    // 计算子节点数量
    childrenCount(data) {
      let count = data?.length ?? 0;
      if (count == 0) return count;
      for (let item of data) {
        // 如果有子节点且子节点不隐藏
        if (item.children.length && this.dataList.hideList[item.id] != true) {
          count = count + this.childrenCount(item.children);
        }
      }
      return count;
    },
    // 上一个子节点数量，然后算出垂直距离
    predecessorsVerticalDistance(self) {
      const index = this.data.findIndex(item => item.id === self.id);
      const startIndex = this.data.findIndex(item => item.id === self.predecessors);
      let total = 0;
      for (let i = startIndex; i < index;i++) {
        // 判断是否折叠了子元素
        if (this.dataList.hideList[this.data[i].id] != true) total += this.childrenCount(this.data[i].children) + 1;
        else total += 1
      }
      return total * height - 21;
    },
    // 计算横向距离
    predecessorsHorizontalDistance(self) {
      const targetNode = this.data.find(item => item.id === self.predecessors);
      let count = total_time(targetNode.endTime, self.startTime) - 2;
      let width = this.width * count;
      if (count === 0) width = 20;
      if (count < 0) width = Math.abs(this.width * count) + 25;
      return width;
    },
    // 计算是否取值： 如果 前辈项目的日期 小于 当前项目开始的日期
    wttaValue(self) {
      const targetNode = this.data.find(item => item.id === self.predecessors);
      return new Date(targetNode.endTime).getTime() + oneDay < new Date(self.startTime).getTime();
    }
  }
}
</script>

<style lang="scss">
$prompt-color: #ffa011;
// 进度条定位
.progress_position {
  position: relative;
  overflow: hidden;
  .el-progress-bar__outer {
    background-color: #ededed;
  }
  .el-progress-bar__outer, .el-progress-bar__inner {
    border-radius: 2px!important;
  }
}
.task_name {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 999;
}
.progress_total {
  position: absolute;
  z-index: 1;
  top: 3px;
}
.progress_ing {
  position: absolute;
  z-index: 1;
  top: 20px;
}
.progress_start {
  z-index: 999;
  position: absolute;
  top: 15PX;
  left: 0;
  // background-color: $prompt-color;
  background-color: #67c23a;
  width: 1px;
}
// 关联线
.associate_line {
  z-index: 0;
  position: absolute;
  background-color: $prompt-color;
}
$size: 4px;
.associate_arrow {
  position: absolute;
  border: $size solid $prompt-color;
  border-left: $size solid transparent!important;
  border-top: $size solid transparent!important;
  transform: rotate(-45deg);
}
</style>